package com.wfg.expresscompany.component;

import com.wfg.expresscompany.Service.ShippingChannels;
import com.wfg.expresscompany.enums.ShippingChannelsEnum;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * @author: 王富贵
 * @description: 发货渠道工厂
 * @createTime: 2023/05/24 22:13
 * 三种方法: 使用工厂模式，注册处理器。使用枚举key用于调用对应抽象方法
 */
@Component
public class ShippingChannelsFactory {

    private static final HashMap<ShippingChannelsEnum, ShippingChannels> shippingChannelsMaps = new HashMap<>();

    @Resource
    private List<ShippingChannels> shippingChannels;

    @Resource
    private ApplicationContext applicationContext;

    @PostConstruct
    private void init() {
        // initByIoc(); // 方法1: 注入方式，通过ioc初始化
        // initByContext(); // 方法2: 通过容器获取集合进行初始化
    }

    /**
     * 方法1: 注入实现，进行初始化
     */
    private void initByIoc() {
        for (ShippingChannels shippingChannel : shippingChannels) {
            shippingChannelsMaps.put(shippingChannel.getShippingChannels(), shippingChannel);
        }
    }

    /**
     * 方法2: 通过容器获取集合进行初始化
     */
    private void initByContext() {
        applicationContext.getBeansOfType(ShippingChannels.class)
                .values().forEach(shippingChannel -> shippingChannelsMaps.put(shippingChannel.getShippingChannels(), shippingChannel));
    }

    /**
     * 方法3: 通过每个实现的@PostConstruct，主动注入
     *
     * @param shippingChannelsEnum 实现名称枚举
     * @param shippingChannel      实现实体
     */
    public static void registerShippingChannels(ShippingChannelsEnum shippingChannelsEnum, ShippingChannels shippingChannel) {
        shippingChannelsMaps.put(shippingChannelsEnum, shippingChannel);
    }

    /**
     * 通过枚举获取媒介实现
     *
     * @param shippingChannelsEnum 渠道枚举
     * @return
     */
    public static ShippingChannels getShippingChannels(ShippingChannelsEnum shippingChannelsEnum) {
        // 获取渠道，没有默认使用汽车
        return Optional.ofNullable(shippingChannelsMaps.get(shippingChannelsEnum))
                .orElse(shippingChannelsMaps.get(ShippingChannelsEnum.CART));
    }
}
